package com.auto.signup.weixin.impl;

import com.auto.signup.weixin.WebAuthScopeEnum;
import com.auto.signup.weixin.WeixinWebAuth;
import com.auto.signup.weixin.exception.AuthException;
import com.auto.signup.weixin.model.WebAuthTokenModel;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriTemplate;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 微信网页授权实现
 * 
 * @author randyjie
 *
 */
@Service
public class WeixinWebAuthImpl implements WeixinWebAuth {

	private final Logger logger = LoggerFactory.getLogger(WeixinWebAuthImpl.class);

	private final static String AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={appid}&redirect_uri={redirect_uri}&response_type=code&scope={scope}&state={state}#wechat_redirect";
	private final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}&grant_type=authorization_code";

	@Value("${tp.weixin.appid}")
	private String appid;
	@Value("${tp.weixin.secret}")
	private String secret;
	//

	@Autowired
	private RestTemplate restTemplate;

	@Override
	public String buildAuthURL(String redirectUri, WebAuthScopeEnum scope, String state) {
		// try {
		// redirectUri = URLEncoder.encode(redirectUri, "utf-8");
		// } catch (UnsupportedEncodingException e) {
		// logger.error("buildAuthURL error:", e.getMessage());
		// return null;
		// }
		Map<String, String> urlVariables = new HashMap<String, String>();
		urlVariables.put("appid", appid);
		urlVariables.put("redirect_uri", redirectUri);
		urlVariables.put("scope", scope.name());
		urlVariables.put("state", state);

		UriTemplate uriTemplate = new UriTemplate(AUTHORIZE_URL);
		return uriTemplate.expand(urlVariables).toString();
	}

	@Override
	public WebAuthTokenModel getAuthToken(String code) throws AuthException {
		//
		Map<String, String> urlVariables = new HashMap<String, String>();
		urlVariables.put("appid", appid);
		urlVariables.put("secret", secret);
		urlVariables.put("code", code);
		ResponseEntity<String> entity = restTemplate.getForEntity(ACCESS_TOKEN_URL, String.class, urlVariables);
		/// 简单版本
		if (entity.getStatusCode().is2xxSuccessful()) {
			ObjectMapper mapper = new ObjectMapper();
			Map<String, Object> map = null;
			try {
				map = mapper.readValue(entity.getBody(), new TypeReference<Map<String, Object>>() {
				});
			} catch (IOException e) {
				logger.error("ACCESS TOKEN IOException：{}", e.getMessage());
				throw new AuthException(500, e.getMessage());
			}
			int errorcode = Integer.valueOf(Objects.toString(map.get("errcode"), "0"));
			if (errorcode != 0) {
				//
				String errorMsg = Objects.toString(map.get("errmsg"), "Unknown Error.");
				logger.error("ACCESS TOKEN ERROR：{}，error code:{}", errorMsg, errorcode);
				throw new AuthException(errorcode, errorMsg);
			} else {
				logger.info("ACCESS TOKEN SUCCESS.");
				WebAuthTokenModel tokenModel = new WebAuthTokenModel(map);
				return tokenModel;
			}
		} else {
			throw new AuthException(entity.getStatusCode().getReasonPhrase());
		}
	}

}
